package com.atguigu.tingshu.album.service.impl;

import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackStatMapper;
import com.atguigu.tingshu.album.service.TrackInfoService;
import com.atguigu.tingshu.album.service.VodService;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.album.TrackStat;
import com.atguigu.tingshu.model.user.UserPaidTrack;
import com.atguigu.tingshu.query.album.TrackInfoQuery;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.atguigu.tingshu.vo.album.*;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tencentcloudapi.vod.v20180717.models.MediaTrack;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartFile;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class TrackInfoServiceImpl extends ServiceImpl<TrackInfoMapper, TrackInfo> implements TrackInfoService {

    @Autowired
    private TrackInfoMapper trackInfoMapper;

    @Autowired
    private TrackStatMapper trackStatMapper;

    @Autowired
    private AlbumInfoMapper albumInfoMapper;

    @Autowired
    private VodService vodService;

    @Autowired
    private UserInfoFeignClient userInfoFeignClient;

    /**
     * 保存声音
     *
     * @param trackInfoVo
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveTrackInfo(TrackInfoVo trackInfoVo, Long userId) {
        try {
            // track_info track_stat album_info
            TrackInfo trackInfo = new TrackInfo();
            // 有相同的属性值，进行属性拷贝
            BeanUtils.copyProperties(trackInfoVo, trackInfo);
            // 赋值用户id
            trackInfo.setUserId(userId);
            // order_num赋值; 第一种：查询当前专辑对应的声音集数+1; 第二种：查询专辑包含声音总数+1;
            AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfoVo.getAlbumId());
            trackInfo.setOrderNum(albumInfo.getIncludeTrackCount() + 1);
            // 处理流媒体的数据; 时长，类型这些数据页面没有传递：fileId 查询流媒体数据，然后赋值。调用云点播的api;
            TrackMediaInfoVo trackMediaInfoVo = vodService.getMediaInfo(trackInfoVo.getMediaFileId());
            // 赋值
            trackInfo.setMediaUrl(trackMediaInfoVo.getMediaUrl());
            trackInfo.setMediaDuration(trackMediaInfoVo.getDuration());
            trackInfo.setMediaType(trackMediaInfoVo.getType());
            trackInfo.setMediaSize(trackMediaInfoVo.getSize());
            // 保存声音
            trackInfoMapper.insert(trackInfo);

            // track_stat   (声音统计 0701-播放量 0702-收藏量 0703-点赞量 0704-评论数)
            saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_PLAY); //0701
            saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_COLLECT); //0702
            saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_PRAISE); //0703
            saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_COMMENT); //0704

            // album_info; 更新数据（包含声音+1）
            albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount() + 1);
            albumInfoMapper.updateById(albumInfo);
        } catch (BeansException e) {
            log.error("保存声音信息失败：{}", e);
            throw new RuntimeException(e);
        }
    }

    /**
     * 保存声音统计数据
     *
     * @param id
     * @param trackStatPlay
     */
    public void saveTrackStat(Long trackId, String statPlay) {
        TrackStat trackStat = new TrackStat();
        // 赋值
        trackStat.setTrackId(trackId);
        trackStat.setStatType(statPlay);
        trackStat.setStatNum(new Random().nextInt(1000));
        // 保存数据
        trackStatMapper.insert(trackStat);
    }


    /**
     * 分页查询声音列表
     *
     * @param trackListVoPage
     * @param trackInfoQuery
     * @return
     */
    @Override
    public IPage<TrackListVo> findUserTrackPage(Page<TrackInfoVo> trackListVoPage, TrackInfoQuery trackInfoQuery) {
        return trackInfoMapper.selectUserTrackPage(trackListVoPage, trackInfoQuery);
    }


    /**
     * 根据声音Id删除声音数据
     *
     * @param trackId
     */
    @Override
    public void removeTrackInfo(Long trackId) {
        // 查询当前声音对象
        TrackInfo trackInfo = this.getById(trackId);
        // track_info  track_stat album_info
        // 删除track_info
        trackInfoMapper.deleteById(trackId);
        // 删除track_stat
        trackStatMapper.delete(new LambdaQueryWrapper<TrackStat>().eq(TrackStat::getTrackId, trackId));
        // album_info 更新 include_track_count （包含声音数量 -1）
        AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfo.getAlbumId());
        albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount() - 1);
        // 更新albumInfo
        albumInfoMapper.updateById(albumInfo);
        // 对 order_num 进行更改（声音在专辑中的排序值 is_deleted = 0）
        // update track_info set order_num = order_num - 1 where album_id = 1 and order_num > 52 and is_deleted = 0
        trackInfoMapper.updateOrderNum(trackInfo.getAlbumId(), trackInfo.getOrderNum());
        // 删除云点播中没有用的声音记录;
        vodService.deleteMediaFile(trackInfo.getMediaFileId());

    }

    /**
     * 修改声音数据
     *
     * @param trackId
     * @param trackInfoVo
     */
    @Override
    public void updateTrackInfo(Long trackId, TrackInfoVo trackInfoVo) {

        TrackInfo trackInfo = this.getById(trackId);
        //	获取原始的文件Id
        String originMediaFileId = trackInfo.getMediaFileId();
        //	属性拷贝
        BeanUtils.copyProperties(trackInfoVo, trackInfo);
        //	判断声音是否被修改
        if (!originMediaFileId.equals(trackInfoVo.getMediaFileId())) {
            //	修改了声音
            TrackMediaInfoVo mediaInfo = vodService.getMediaInfo(trackInfoVo.getMediaFileId());
            //	赋值最新流媒体数据
            trackInfo.setMediaType(mediaInfo.getType());
            trackInfo.setMediaDuration(mediaInfo.getDuration());
            trackInfo.setMediaSize(mediaInfo.getSize());
            trackInfo.setMediaFileId(trackInfoVo.getMediaFileId());
            //	原有的不要了
            vodService.deleteMediaFile(originMediaFileId);
        }
        //	更新数据;
        this.updateById(trackInfo);
    }

    /**
     * 获取专辑对应的声音列表
     *
     * @param albumTrackListVoPage
     * @param albumId
     * @param userId
     * @return
     */
    @Override
    public IPage<AlbumTrackListVo> findAlbumTrackPage(Page<AlbumTrackListVo> albumTrackListVoPage, Long albumId, Long userId) {
        /*1.先根据专辑id获取到声音列表
            2.判断用户是否登录  null != userId,  null == userId
                2.1 判断专辑类型
                2.2 除用户已购买的声音id
        */
        IPage<AlbumTrackListVo> albumTrackListVoIPage = trackInfoMapper.selectAlbumTrackList(albumTrackListVoPage, albumId);
        // 查询专辑类型
        AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
        // 判断用户是否登录
        if (null == userId) {
            // 没有登录,专辑类型是付费时，除免费试听声音都需要付费
            if (SystemConstant.ALBUM_PAY_TYPE_FREE.equals(albumInfo.getPayType())) {
                // 免费试听集数：5
                Integer tracksForFree = albumInfo.getTracksForFree();
                // 除免费试听声音都需要付费
                albumTrackListVoIPage.getRecords().stream().filter(albumTrackListVo -> albumTrackListVo.getOrderNum() > tracksForFree)
                        .forEach(albumTrackListVo -> albumTrackListVo.setIsShowPaidMark(true));
            }
        } else {
            // 获取用户信息
            Result<UserInfoVo> userInfoVoResult = userInfoFeignClient.getUserInfoVo(userId);
            Assert.notNull(userInfoVoResult, "查询用户信息失败");
            UserInfoVo userInfoVo = userInfoVoResult.getData();
            Assert.notNull(userInfoVo, "查询用户信息失败");
            // 设置一个变量，记录是否需要付费，false 免费， true 付费
            boolean isPaid = false;
            // 判断专辑的类型，vip免费
            if (SystemConstant.ALBUM_PAY_TYPE_VIPFREE.equals(albumInfo.getPayType())) {
                //  前提是用户是vip且过期
                if ((userInfoVo.getIsVip() == 1 && userInfoVo.getVipExpireTime().before(new Date())) || userInfoVo.getIsVip() == 0) {
                    // 需要付费
                    isPaid = true;
                }
            } else if (SystemConstant.ALBUM_PAY_TYPE_REQUIRE.equals(albumInfo.getPayType())) {
                // 必须付费
                isPaid = true;
            }
            // 判断需要付费的情况
            if (isPaid) {
                // 远程调用，需要直到用户购买了哪些声音；专辑id；付费声音了列表userId--从本地线程中获取
                List<AlbumTrackListVo> albumTrackListVoList = albumTrackListVoIPage.getRecords().stream().filter(albumTrackListVo -> albumTrackListVo.getOrderNum() > albumInfo.getTracksForFree())
                        .collect(Collectors.toList());
                // 这个是付费声音id
                List<Long> trackIdList = albumTrackListVoList.stream().map(AlbumTrackListVo::getTrackId).collect(Collectors.toList());
                // 获取用户购买的声音列表，如果用户购买了，将购买的声音id与状态存储到map集合中，map.put(trackId,1)-买过; map.put(trackId,0)-未买过;
                Result<Map<Long, Integer>> mapResult = userInfoFeignClient.userIsPaidTrack(albumId, trackIdList);
                Assert.notNull(mapResult, "查询用户购买声音失败");
                Map<Long, Integer> map = mapResult.getData();
                //  map.put(trackId,1)-买过; map.put(trackId,0)-未买过;
                for (AlbumTrackListVo albumTrackListVo : albumTrackListVoList) {
                    //  Boolean isPaidMark = map.get(albumTrackListVo.getTrackId()) == 1 ? false : true;
                    //  Boolean isPaidMark1 = map.get(albumTrackListVo.getTrackId()) == 0 ? true : false;
                    //  默认是isShowPaidMark = false;
                    albumTrackListVo.setIsShowPaidMark(map.get(albumTrackListVo.getTrackId()) == 0);
                }
            }
        }
        // 返回数据；
        return albumTrackListVoIPage;
    }

    /**
     * 监听器：更新声音的播放量和更新专辑的播放量
     *
     * @param trackStatMqVo
     */
    @Override
    public void updateTrackStat(TrackStatMqVo trackStatMqVo) {
        // 1. 更新声音的播放量：update track_stat set stat_num = stat_num + 1 where track_id = ? and stat_type = '0701' and is_deleted = 0
        // 判断是否属于播放量
        if (SystemConstant.TRACK_STAT_PLAY.equals(trackStatMqVo.getStatType())) {
            // 1.更新声音播放量
            trackInfoMapper.updateTrackStat(trackStatMqVo.getCount(), trackStatMqVo.getTrackId(), trackStatMqVo.getStatType());
            // 2.更新专辑播放量
            albumInfoMapper.updateAlbumStat(trackStatMqVo.getCount(), trackStatMqVo.getAlbumId(), SystemConstant.ALBUM_STAT_PLAY);
        } else if (SystemConstant.TRACK_STAT_COLLECT.equals(trackStatMqVo.getStatType())) {
            // 暂无
        }
    }

    /**
     * 获取用户声音分集购买支付列表
     *
     * @param trackId
     * @param userId
     * @return
     */
    @Override
    public List<Map<String, Object>> findUserTrackPaidList(Long trackId, Long userId) {
        // 创建返回对象
        List<Map<String, Object>> list = new ArrayList<>();
        // 根据声音id获取声音信息
        TrackInfo trackInfo = trackInfoMapper.selectById(trackId);
        // 获取当前声音id的排序
        Integer orderNum = trackInfo.getOrderNum();
        // 远程调用获取当前用户已购买的声音id列表
        Result<List<Long>> userPaidTrackList = userInfoFeignClient.findUserPaidTrackList(trackInfo.getAlbumId());
        Assert.notNull(userPaidTrackList, "查询用户购买声音列表失败");
        List<Long> trackIdList = userPaidTrackList.getData();
        // 从当前声音Id开始计算有多少声音是需要付费的集合Id;
        //select * from track_info where order_num > 8 and album_id = 1334
        List<TrackInfo> trackInfoList = trackInfoMapper.selectList(new LambdaQueryWrapper<TrackInfo>().gt(TrackInfo::getOrderNum, trackInfo.getOrderNum())
                .eq(TrackInfo::getUserId, userId));
        // 两个集合取差集,需要付费的声音列表;
        List<TrackInfo> paidTrackIdList = trackInfoList.stream().filter(trackInfoItem -> !trackIdList.contains(trackInfoItem.getId())).collect(Collectors.toList());
        // 根据专辑Id获取专辑对象
        AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfo.getAlbumId());
        // 判断
        if (paidTrackIdList.size() >= 0) {
            // 显示本集
            HashMap<String, Object> map = new HashMap<>();
            map.put("name", "本集");
            // 每一集声音的钱数
            map.put("price", albumInfo.getPrice());
            map.put("trackCount", 0);
            // 添加本集到集合
            list.add(map);
        }
        // 后9集
        if (paidTrackIdList.size() > 0 && paidTrackIdList.size() <= 10) {
            // 显示后size集
            HashMap<String, Object> map = new HashMap<>();
            map.put("name", "后" + paidTrackIdList.size() + "集");
            // 每一集声音的钱数
            map.put("price", albumInfo.getPrice().multiply(new BigDecimal(String.valueOf(paidTrackIdList.size()))));
            map.put("trackCount", paidTrackIdList.size());
            // 添加到集合
            list.add(map);
        }
        // 后10集
        if (paidTrackIdList.size() > 10) {
            // 显示后size集
            HashMap<String, Object> map = new HashMap<>();
            map.put("name", "后10集");
            // 每一集声音的钱数
            map.put("price", albumInfo.getPrice().multiply(new BigDecimal("10")));
            map.put("trackCount", 10);
            // 添加到集合
            list.add(map);
        }
        //  后9集
        if (paidTrackIdList.size() > 10 && paidTrackIdList.size() <= 20) {
            //  显示后size集;
            HashMap<String, Object> map = new HashMap<>();
            map.put("name", "后" + paidTrackIdList.size() + "集");
            //  当前每一集声音的钱数;
            map.put("price", albumInfo.getPrice().multiply(new BigDecimal(String.valueOf(paidTrackIdList.size()))));
            map.put("trackCount", paidTrackIdList.size());
            //  添加本集到集合;
            list.add(map);
        }
        //  后10集;
        if (paidTrackIdList.size() > 20) {
            //  后10集合;
            HashMap<String, Object> map = new HashMap<>();
            map.put("name", "后20集");
            //  当前每一集声音的钱数;
            map.put("price", albumInfo.getPrice().multiply(new BigDecimal("20")));
            map.put("trackCount", 20);
            //  添加本集到集合;
            list.add(map);
        }
        // 返回数据
        return list;
    }

}
